Improve error handling for enum/flags, rename the converter functions to
authorJohan Dahlin <jdahlin@async.com.br>
Sat, 30 Jun 2007 18:27:39 +0000 (18:27 +0000)
committerJohan Dahlin <johan@src.gnome.org>
Sat, 30 Jun 2007 18:27:39 +0000 (18:27 +0000)
2007-06-30  Johan Dahlin  <jdahlin@async.com.br>

    * gtk/gtkbuilder.c:
    * gtk/gtkbuilder.h:
    * gtk/gtkbuilderparser.c:
    * gtk/gtkbuilderprivate.h:
    * gtk/gtkwidget.c:
    * tests/buildertest.c:

    Improve error handling for enum/flags, rename the converter functions
    to be consistent. Add tests. Fixes #452465

svn path=/trunk/; revision=18312

ChangeLog
gtk/gtkbuilder.c
gtk/gtkbuilder.h
gtk/gtkbuilderparser.c
gtk/gtkbuilderprivate.h
gtk/gtkwidget.c
tests/buildertest.c

index ccf524f2f2f23cd8d5d05a9663e19d01ac245e8b..d9a0b5b1c75a110d54b4fd6362270147b1e0d9c2 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,15 @@
+2007-06-30  Johan Dahlin  <jdahlin@async.com.br>
+
+       * gtk/gtkbuilder.c:
+       * gtk/gtkbuilder.h:
+       * gtk/gtkbuilderparser.c:
+       * gtk/gtkbuilderprivate.h:
+       * gtk/gtkwidget.c: 
+       * tests/buildertest.c:
+
+       Improve error handling for enum/flags, rename the converter functions
+       to be consistent. Add tests. Fixes #452465
+
 2007-06-30  Richard Hult  <richard@imendio.com>
 
        * gdk/quartz/gdkwindow-quartz.c: (gdk_window_get_origin): Make
index 22228acdc19863c205fcfd1057ed8dab7c4c1254..167a815b9bdd5c723d53cdd6607c08997c31e688 100644 (file)
@@ -49,8 +49,10 @@ static void gtk_builder_get_property   (GObject         *object,
                                         GParamSpec      *pspec);
 static GType gtk_builder_real_get_type_from_name (GtkBuilder  *builder,
                                                   const gchar *type_name);
-static gint _gtk_builder_enum_from_string        (GType        type, 
-                                                  const gchar *string);
+static gboolean _gtk_builder_enum_from_string (GType         type, 
+                                              const gchar  *string,
+                                              gint         *enum_value,
+                                              GError      **error);
 
 
 enum {
@@ -1038,7 +1040,7 @@ gtk_builder_value_from_string_type (GtkBuilder   *builder,
       {
         gboolean b;
 
-       if (!_gtk_builder_parse_boolean (string, &b, error))
+       if (!_gtk_builder_boolean_from_string (string, &b, error))
          {
            ret = FALSE;
            break;
@@ -1093,11 +1095,27 @@ gtk_builder_value_from_string_type (GtkBuilder   *builder,
         break;
       }
     case G_TYPE_ENUM:
-      g_value_set_enum (value, _gtk_builder_enum_from_string (type, string));
-      break;
+      {
+       gint enum_value;
+       if (!_gtk_builder_enum_from_string (type, string, &enum_value, error))
+         {
+           ret = FALSE;
+           break;
+          }
+       g_value_set_enum (value, enum_value);
+       break;
+      }
     case G_TYPE_FLAGS:
-      g_value_set_flags (value, _gtk_builder_flags_from_string (type, string));
-      break;
+      {
+       gint flags_value;
+       if (!_gtk_builder_flags_from_string (type, string, &flags_value, error))
+         {
+           ret = FALSE;
+           break;
+          }
+       g_value_set_flags (value, flags_value);
+       break;
+      }
     case G_TYPE_FLOAT:
     case G_TYPE_DOUBLE:
       {
@@ -1195,42 +1213,57 @@ gtk_builder_value_from_string_type (GtkBuilder   *builder,
   return ret;
 }
 
-static gint
-_gtk_builder_enum_from_string (GType        type, 
-                               const gchar *string)
+static gboolean
+_gtk_builder_enum_from_string (GType         type, 
+                               const gchar  *string,
+                              gint         *enum_value,
+                              GError      **error)
 {
   GEnumClass *eclass;
   GEnumValue *ev;
   gchar *endptr;
-  gint ret = 0;
-
+  gint value;
+  
   g_return_val_if_fail (G_TYPE_IS_ENUM (type), 0);
   g_return_val_if_fail (string != NULL, 0);
   
-  ret = strtoul (string, &endptr, 0);
+  value = strtoul (string, &endptr, 0);
   if (endptr != string) /* parsed a number */
-    return ret;
-
-  eclass = g_type_class_ref (type);
-  ev = g_enum_get_value_by_name (eclass, string);
-  if (!ev)
-    ev = g_enum_get_value_by_nick (eclass, string);
-
-  if (ev)
-    ret = ev->value;
-
-  g_type_class_unref (eclass);
+    *enum_value = value;
+  else
+    {
+      eclass = g_type_class_ref (type);
+      ev = g_enum_get_value_by_name (eclass, string);
+      if (!ev)
+       ev = g_enum_get_value_by_nick (eclass, string);
 
-  return ret;
+      if (ev)
+       *enum_value = ev->value;
+      else
+       {
+         g_set_error (error,
+                      GTK_BUILDER_ERROR,
+                      GTK_BUILDER_ERROR_INVALID_VALUE,
+                      "Could not parse enum: `%s'",
+                      string);
+         return FALSE;
+       }
+      
+      g_type_class_unref (eclass);
+    }
+  
+  return TRUE;
 }
 
-guint
-_gtk_builder_flags_from_string (GType        type, 
-                                const gchar *string)
+gboolean
+_gtk_builder_flags_from_string (GType         type, 
+                                const gchar  *string,
+                               gint         *flags_value,
+                               GError      **error)
 {
   GFlagsClass *fclass;
   gchar *endptr, *prevptr;
-  guint i, j, ret;
+  guint i, j, ret, value;
   gchar *flagstr;
   GFlagsValue *fv;
   const gchar *flag;
@@ -1240,70 +1273,85 @@ _gtk_builder_flags_from_string (GType        type,
   g_return_val_if_fail (G_TYPE_IS_FLAGS (type), 0);
   g_return_val_if_fail (string != 0, 0);
 
-  ret = strtoul (string, &endptr, 0);
+  ret = TRUE;
+  
+  value = strtoul (string, &endptr, 0);
   if (endptr != string) /* parsed a number */
-    return ret;
-
-  fclass = g_type_class_ref (type);
-
-  flagstr = g_strdup (string);
-  for (ret = i = j = 0; ; i++)
+    *flags_value = value;
+  else
     {
+      fclass = g_type_class_ref (type);
 
-      eos = flagstr[i] == '\0';
-
-      if (!eos && flagstr[i] != '|')
-        continue;
-
-      flag = &flagstr[j];
-      endptr = &flagstr[i];
-
-      if (!eos)
-        {
-          flagstr[i++] = '\0';
-          j = i;
-        }
-
-      /* trim spaces */
-      for (;;)
-        {
-          ch = g_utf8_get_char (flag);
-          if (!g_unichar_isspace (ch))
-            break;
-          flag = g_utf8_next_char (flag);
-        }
-
-      while (endptr > flag)
-        {
-          prevptr = g_utf8_prev_char (endptr);
-          ch = g_utf8_get_char (prevptr);
-          if (!g_unichar_isspace (ch))
-            break;
-          endptr = prevptr;
-        }
-
-      if (endptr > flag)
-        {
-          *endptr = '\0';
-          fv = g_flags_get_value_by_name (fclass, flag);
-
-          if (!fv)
-            fv = g_flags_get_value_by_nick (fclass, flag);
-
-          if (fv)
-            ret |= fv->value;
-          else
-            g_warning ("Unknown flag: '%s'", flag);
-        }
-
-      if (eos)
-        break;
+      flagstr = g_strdup (string);
+      for (value = i = j = 0; ; i++)
+       {
+         
+         eos = flagstr[i] == '\0';
+         
+         if (!eos && flagstr[i] != '|')
+           continue;
+         
+         flag = &flagstr[j];
+         endptr = &flagstr[i];
+         
+         if (!eos)
+           {
+             flagstr[i++] = '\0';
+             j = i;
+           }
+         
+         /* trim spaces */
+         for (;;)
+           {
+             ch = g_utf8_get_char (flag);
+             if (!g_unichar_isspace (ch))
+               break;
+             flag = g_utf8_next_char (flag);
+           }
+         
+         while (endptr > flag)
+           {
+             prevptr = g_utf8_prev_char (endptr);
+             ch = g_utf8_get_char (prevptr);
+             if (!g_unichar_isspace (ch))
+               break;
+             endptr = prevptr;
+           }
+         
+         if (endptr > flag)
+           {
+             *endptr = '\0';
+             fv = g_flags_get_value_by_name (fclass, flag);
+             
+             if (!fv)
+               fv = g_flags_get_value_by_nick (fclass, flag);
+             
+             if (fv)
+               value |= fv->value;
+             else
+               {
+                 g_set_error (error,
+                              GTK_BUILDER_ERROR,
+                              GTK_BUILDER_ERROR_INVALID_VALUE,
+                              "Unknown flag: `%s'",
+                              flag);
+                 ret = FALSE;
+                 break;
+               }
+           }
+         
+         if (eos)
+           {
+             *flags_value = value;
+             break;
+           }
+       }
+      
+      g_free (flagstr);
+      
+      g_type_class_unref (fclass);
     }
 
-  g_free (flagstr);
-
-  g_type_class_unref (fclass);
-
   return ret;
 }
 
index 0886d2a2d145cb44637f4ff4b83506821346b525..732acaa15e9b9f95cb49d3693abe96e46ac7400e 100644 (file)
@@ -117,8 +117,6 @@ gboolean     gtk_builder_value_from_string_type  (GtkBuilder    *builder,
                                                   const gchar          *string,
                                                   GValue               *value,
                                                  GError       **error);
-guint        _gtk_builder_flags_from_string      (GType         type,
-                                                 const char    *string);
 
 #define GTK_BUILDER_WARN_INVALID_CHILD_TYPE(object, type) \
   g_warning ("'%s' is not a valid child type of '%s'", type, g_type_name (G_OBJECT_TYPE (type)))
index a1e31a11872de5cf4020f4678d07ef7dc1b92891..2996ac8a4ffafab8fd6450b2493e465cb4973ff9 100644 (file)
@@ -158,12 +158,11 @@ error_missing_property_value (ParserData *data,
 }
 
 gboolean
-_gtk_builder_parse_boolean (const gchar  *string,
-                           gboolean     *value,
-                           GError      **error)
+_gtk_builder_boolean_from_string (const gchar  *string,
+                                 gboolean     *value,
+                                 GError      **error)
 {
   gboolean retval = TRUE;
-  int i;
   int length;
   
   g_assert (string != NULL);
@@ -405,7 +404,8 @@ parse_property (ParserData   *data,
         name = g_strdelimit (g_strdup (values[i]), "_", '-');
       else if (strcmp (names[i], "translatable") == 0)
        {
-         if (!_gtk_builder_parse_boolean (values[i], &translatable, error))
+         if (!_gtk_builder_boolean_from_string (values[i], &translatable,
+                                                error))
            return;
        }
       else
@@ -463,12 +463,12 @@ parse_signal (ParserData   *data,
         handler = g_strdup (values[i]);
       else if (strcmp (names[i], "after") == 0)
        {
-         if (!_gtk_builder_parse_boolean (values[i], &after, error))
+         if (!_gtk_builder_boolean_from_string (values[i], &after, error))
            return;
        }
       else if (strcmp (names[i], "swapped") == 0)
        {
-         if (!_gtk_builder_parse_boolean (values[i], &swapped, error))
+         if (!_gtk_builder_boolean_from_string (values[i], &swapped, error))
            return;
          swapped_set = TRUE;
        }
index 11d8974a77d48c46c37580c100cc96ddded9e1a9..70c9f7941f8c37e85eb7166e502159418e7ebc54 100644 (file)
@@ -107,8 +107,12 @@ void      _gtk_builder_add (GtkBuilder *builder,
 void      _gtk_builder_finish (GtkBuilder *builder);
 void _free_signal_info (SignalInfo *info,
                         gpointer user_data);
-gboolean _gtk_builder_parse_boolean (const gchar  *string,
-                                    gboolean     *value,
-                                    GError      **error);
+gboolean _gtk_builder_boolean_from_string (const gchar  *string,
+                                          gboolean     *value,
+                                          GError      **error);
+gboolean  _gtk_builder_flags_from_string (GType       type,
+                                         const char *string,
+                                         gint       *value,
+                                         GError    **error);
 
 #endif /* __GTK_BUILDER_PRIVATE_H__ */
index 2a54b6e9e3a138aab24fadc9ef3db6f0265614ed..25fcb5f1fe156482f40f006fcb8b25c638bd5b3c 100644 (file)
@@ -53,6 +53,7 @@
 #include "gtktooltip.h"
 #include "gtkinvisible.h"
 #include "gtkbuildable.h"
+#include "gtkbuilderprivate.h"
 #include "gtkalias.h"
 
 #define WIDGET_CLASS(w)         GTK_WIDGET_GET_CLASS (w)
@@ -8517,7 +8518,13 @@ accel_group_start_element (GMarkupParseContext *context,
       if (strcmp (names[i], "key") == 0)
        key = gdk_keyval_from_name (values[i]);
       else if (strcmp (names[i], "modifiers") == 0)
-       modifiers = _gtk_builder_flags_from_string (GDK_TYPE_MODIFIER_TYPE, values[i]);
+       {
+         if (!_gtk_builder_flags_from_string (GDK_TYPE_MODIFIER_TYPE,
+                                              values[i],
+                                              &modifiers,
+                                              error))
+             return;
+       }
       else if (strcmp (names[i], "signal") == 0)
        signal = g_strdup (values[i]);
     }
index fb443a74e9fd2681266e51ff62af0c26b094a9d8..86e4d9fe46bb695972f19314977e0fee0e72dc31 100644 (file)
@@ -1602,6 +1602,35 @@ test_value_from_string (void)
   g_error_free (error);
   error = NULL;
 
+  g_return_val_if_fail (gtk_builder_value_from_string_type (builder, GTK_TYPE_WINDOW_TYPE, "toplevel", &value, &error) == TRUE, FALSE);
+  g_return_val_if_fail (G_VALUE_HOLDS_ENUM (&value), FALSE);
+  g_return_val_if_fail (g_value_get_enum (&value) == GTK_WINDOW_TOPLEVEL, FALSE);
+  g_value_unset (&value);
+
+  g_return_val_if_fail (gtk_builder_value_from_string_type (builder, GTK_TYPE_WINDOW_TYPE, "sliff", &value, &error) == FALSE, FALSE);
+  g_value_unset (&value);
+  g_return_val_if_fail (error->domain == GTK_BUILDER_ERROR, FALSE);
+  g_return_val_if_fail (error->code == GTK_BUILDER_ERROR_INVALID_VALUE, FALSE);
+  g_error_free (error);
+  error = NULL;
+  
+  g_return_val_if_fail (gtk_builder_value_from_string_type (builder, GTK_TYPE_WIDGET_FLAGS, "mapped", &value, &error) == TRUE, FALSE);
+  g_return_val_if_fail (G_VALUE_HOLDS_FLAGS (&value), FALSE);
+  g_return_val_if_fail (g_value_get_flags (&value) == GTK_MAPPED, FALSE);
+  g_value_unset (&value);
+
+  g_return_val_if_fail (gtk_builder_value_from_string_type (builder, GTK_TYPE_WIDGET_FLAGS, "GTK_VISIBLE | GTK_REALIZED", &value, &error) == TRUE, FALSE);
+  g_return_val_if_fail (G_VALUE_HOLDS_FLAGS (&value), FALSE);
+  g_return_val_if_fail (g_value_get_flags (&value) == (GTK_VISIBLE | GTK_REALIZED), FALSE);
+  g_value_unset (&value);
+  
+  g_return_val_if_fail (gtk_builder_value_from_string_type (builder, GTK_TYPE_WINDOW_TYPE, "foobar", &value, &error) == FALSE, FALSE);
+  g_value_unset (&value);
+  g_return_val_if_fail (error->domain == GTK_BUILDER_ERROR, FALSE);
+  g_return_val_if_fail (error->code == GTK_BUILDER_ERROR_INVALID_VALUE, FALSE);
+  g_error_free (error);
+  error = NULL;
+  
   g_object_unref (builder);
   
   return TRUE;